﻿namespace PacketRush.Core
{
    /// <summary>
    /// An interface that describes a client/server service that consumes and produces network packets.
    /// </summary>
    /// <remarks>
    /// <para><see cref="PacketRush.Core.NetServer"/> and <see cref="PacketRush.Core.NetClient"/> register services in order to
    /// provide a communication layer, abstracted away from the underlying networking protocol. For each service registered with <c>NetServer</c>, there is a corresponding service registered with <c>NetClient</c>.
    /// </para>
    /// <para>
    /// Services can be registered with <see cref="PacketRush.Core.NetBase.RegisterService"/> for <c>NetServer</c> and <c>NetClient</c>.
    /// </para>
    /// <para>
    /// Although a server-side service and a client-side service both implement <c>INetService</c>, implementations of <c>INetService</c> should distinguish
    /// themselves by having a client-side implementation and a server-side implementation since <c>NetServer</c> and <c>NetClient</c> ussually have different concerns,
    /// for instance a server-side text messaging service would be concerned with delivering messages to all clients when it receives a message from one client,
    /// yet the client-side service only needs to receive text messages and send out text messages to the server.
    /// </para>
    /// 
    /// <para>
    /// During an <see cref="PacketRush.Core.NetServer.Update"/> of <c>NetServer</c> or an <see cref="PacketRush.Core.NetClient.Update"/> of <c>NetClient</c>, packets are received from the network and passed to designated services via the
    /// <see cref="PacketRush.Core.INetService.DeliverPacket"/> method, it is the responsibility of the service implementation to handle and interpret
    /// packets as they are passed.
    /// </para>
    /// <para>
    /// Also during an <c>Update</c>, services are enumerated and for each service repeated calls are made to the service method <see cref="PacketRush.Core.INetService.CollectPacket"/>
    /// until it returns null, indicating that there are no more packets to collect. This gives services the opportunity to construct and send packets across the network.
    /// </para>
    /// <para>
    /// A <see cref="PacketRush.Core.Packet"/>'s destination service is identified by a <see cref="PacketRush.Core.Packet.ServiceId"/> written into the packets header, <c>NetClient</c> and <c>NetServer</c> use this value to determine
    /// which service the packet is delivered to.
    /// </para>
    /// <para>
    /// Currently PacketRush supports up to 128 services, this limitation is due to the service id being encoded into the packet as an sbyte, negative values of the sbyte are used to identify system packets.
    /// </para> 
    /// <para>
    /// <c>NetServer</c> and <c>NetClient</c> have useful events that implementations of <c>INetService</c> may subscribe to, this can be achieved by creating an appropriate constructor for a service implementation and
    /// passing in either <c>NetServer</c> or <c>NetClient</c> during startup.
    /// </para>
    /// </remarks>
    public interface INetService
    {
        /// <summary>
        /// Deliver a packet to this service.
        /// </summary>
        /// <remarks>
        /// <see cref="PacketRush.Core.NetClient"/> and <see cref="PacketRush.Core.NetServer"/> will call this method to deliver a packet to this service.
        /// </remarks>
        /// <param name="packet">The packet to deliver</param>
        void DeliverPacket(Packet packet);

        /// <summary>
        /// Collect a packet from this service.
        /// </summary>
        /// <remarks>
        /// During an <see cref="PacketRush.Core.NetServer.Update"/> of <c>NetServer</c> or an <see cref="PacketRush.Core.NetClient.Update"/> of <c>NetClient</c>, repeated calls
        /// will be made to this method until it returns null, this gives the opportunity for services to prepare packets into queues or some other appropriate mechanism that
        /// are destined to be send across the network to the corresponding service on either the server-side or client-side respectively.
        /// </remarks>
        /// <returns>A packet.</returns>
        Packet CollectPacket();
    }
}